package edu.chalmers.AV_2DPlatformerFramework.Model;

import edu.chalmers.AV_2DPlatformerFramework.Utility.Pair;
import edu.chalmers.AV_2DPlatformerFramework.Utility.Vector2D;
import java.awt.Polygon;
import java.awt.Shape;

/**
 * Represents the main game world. Based on GameObject, but has some restrictions and additional functionality.
 * All edges of the Hitbox must be parallel or perpendicular to the coordinate system.
 * @author Richard Sundqvist
 * @version 1.0
 */
public class GameWorld extends GameObject {
    
    private final Polygon drawingPolygon;
    private final int[][] coords;
    
    /**
     * Constructs the main, static world (ground) from a line whose vertices are
     * either perpendicular or parallel to the axes.
     * @param coords The (x,y) coordinates of the line's vertices.
     * @param position the (x,y) coordinates to translate the line from the initial point.
     */
    public GameWorld(int[][] coords, Vector2D position) {
        super(null);
        this.coords = coords;
        this.setStrata(100);

        int coordsLength = coords[0].length;
        int[] xpoints = new int[coordsLength+2];
        int[] ypoints = new int[coordsLength+2];
        
//        //translation
//        for (int i = 0; i < coordsLength; i++){
//            coords[0][i] = (int)(coords[0][i] + offset.x + 0.5);
//            coords[1][i] = (int)(coords[1][i] + offset.y + 0.5);
//        }

        if (coords[0].length != coords[1].length){
            throw new IllegalArgumentException("Number of x and y coordinates must be equal");
        }
//        //Ensures that all lines are either parallel or perpendicular to the axes.
//        for (int i = 1; i < coordsLength; i++){
//            if (coords[0][i-1] != coords[0][i] && coords[1][i-1] != coords[1][i]){
//                throw new IllegalArgumentException("All edges of the hitbox must be parallel or perpendicular to the coordinate system.");
//            }
//            xpoints[i] = coords[0][i];
//            ypoints[i] = coords[1][i];
//        }
        

        
        //Adds additonal points to convert the line into a polygon.
        xpoints[0] = coords[0][0];
        ypoints[0] = coords[1][0];
        
        xpoints[coordsLength + 0] = coords[0][coordsLength-1] + 0;       
        ypoints[coordsLength + 0] = coords[1][coordsLength-1] + 100;  
        
        xpoints[coordsLength + 1] = coords[0][0];       
        ypoints[coordsLength + 1] = ypoints[coordsLength + 0];
        
        drawingPolygon = new Polygon(xpoints, ypoints, xpoints.length);
        
        //Construct well-formed (hopyfully) hitbox from polygon
        Vector2D[] vertices = new Vector2D[xpoints.length];
        for (int i = 0; i < xpoints.length; i++){
            vertices[i] = new Vector2D(xpoints[i], ypoints[i]);
        }
        try {
            super.setHitbox(new Hitbox(vertices));
        } catch (Hitbox.HitboxMalformedException ex) {
            System.out.println("Failed to construct a Hitbox for:" + ex.getClass().getSimpleName());
        }
        
        super.setPosition(position);
        super.setElasticity(0);
        super.setLayer(new UniversalInteractionLayer());
        super.setVelocity(new Vector2D(0, 0));
        super.setWeight(50000000);
    }
    
    @Override
    public Pair<Texture, Shape> getVisual(){
        return new Pair(getCurrentTexture(), getUpdatedPolygon());
    }
    @Override
    public Polygon getHitboxVisual(){
        return getUpdatedPolygon();
    }
    
    private Polygon getUpdatedPolygon(){
        int s = drawingPolygon.npoints;
        int[] newXPoints = new int[s];
        int[] newYPoints = new int[s];
        
        int dX = (int)(getPosition().x + 0.5);
        int dY = (int)(getPosition().y + 0.5);
        
        for (int i = 0; i < s; i ++){
            newXPoints[i] = drawingPolygon.xpoints[i] + dX;
            newYPoints[i] = drawingPolygon.ypoints[i] + dY;
        }
        return new Polygon(newXPoints, newYPoints, s);
    }

    //Setters
    @Override
    public void setElasticity(double newElasticity){} //Should not be changed.    
    @Override
    public void setVelocity(Vector2D newVelocity){} //Should not be changed.
    @Override
    public void setWeight(double newWeight){} //Should not be changed.
    @Override
    public void setLayer(Layer newLayer){} //Should not be changed.
    
    @Override
    public void onCollision(GameObject otherObject){
//        System.out.println("world!");

    } //Nothing intresting should happen.
    @Override
    public GameObject copy() {
        GameWorld copy = new GameWorld(this.coords, super.getPosition());
        this.copyVariablesTo(copy);
        return copy;
    }
    
    
}
